package org.webball.tools;

import java.io.Serializable;


/**
 * Class represents vector.
 * @author Maciej Koch
 *
 */
public class MKVector implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 3226090074157689346L;
	
	/**
	 * x component
	 */
	public float x;
	/**
	 * y component
	 */
	public float y;
	/**
	 * length of this MKVector
	 */
	public float length;
	
	
	//constructors
	/**
	 * create a new empty MKVector
	 */
	public MKVector()
	{
		
	}
	/**
	 * create a new MKVector
	 * @param x
	 * @param y
	 */
	public MKVector(float x, float y)
	{
		this.x = x;
		this.y = y;
		calculateLength();
	}	
	/**
	 * create a new MKVector based on other MKVector
	 * @param other
	 * - MKVector to copy into this MKVector
	 */
	public MKVector(MKVector other)
	{
		this(other.x, other.y);
	}
	//public methods
	/**
	 * set the values into this MKVector
	 * @param other
	 * - MKVector set into this MKVector
	 * @return this set MKVector
	 */
	public MKVector set(MKVector other)
	{
		if(other == null) return null;
		this.x = other.x;
		this.y = other.y;
		calculateLength();
		return this;
	}
	/**
	 * set the values into this MKVector
	 * @param x
	 * - component x set into this MKVector
	 * @param y
	 * - component y set into this MKVector
	 * @return this set MKVector
	 */
	public MKVector set(float x, float y)
	{
		this.x = x;
		this.y = y;
		calculateLength();
		return this;
	}
	/**
	 * add a MKVector to this MKVector
	 * @param other
	 * - MKVector to add
	 * @return this changed MKVector
	 */
	public MKVector add(MKVector other)
	{
		if(other == null) return null;
		this.x += other.x;
		this.y += other.y;
		calculateLength();
		
		return this;
	}
	/**
	 * add a x,y to this MKVector
	 * @param x
	 * - component x to add to MKVectors component x
	 * @param y
	 * - component y to add to MKVectors component y
	 * @return this changed MKVector
	 */
	public MKVector add(float x, float y)
	{
		this.x += x;
		this.y += y;
		calculateLength();
		
		return this;
	}
	/**
	 * sub a MKVector to this MKVector
	 * @param other
	 * - MKVector to sub
	 * @return this changed MKVector
	 */
	public MKVector sub(MKVector other)
	{
		if(other == null) return null;
		this.x -= other.x;
		this.y -= other.y;
		calculateLength();
		
		return this;
	}
	/**
	 * sub a x,y to this MKVector
	 * @param x
	 * - component x to sub from MKVectors component x
	 * @param y
	 * - component y to sub from MKVectors component y
	 * @return this changed MKVector
	 */
	public MKVector sub(float x, float y)
	{
		this.x -= x;
		this.y -= y;
		calculateLength();
		
		return this;
	}
	/**
	 * normalise this MKVector
	 * @return this normalised MKVector
	 */
	public MKVector normalise()
	{
		this.x /= length;
		this.y /= length;
		calculateLength();
		
		return this;
	}
	/**
	 * calculate distance from other MKVector to this MKVector
	 * @param other
	 * - MKVector we are measuring to
	 * @return distance to other MKVector
	 */
	public float distance(MKVector other)
	{
		//TODO refactor :P
		//usun tego ifa, lepiej zeby komus wywalilo null niz
		//sie glowic co jest nie tak
		if(other == null) return -1;
		return calculateLength(this.x - other.x, this.y - other.y);
	}
	/**
	 * scale this MKVector by a value
	 * @param scale
	 * - the value to scale this MKVector
	 * @return this scaled MKVector
	 */
	public MKVector scale(float scale)
	{
		this.x *= scale;
		this.y *= scale;
		calculateLength();
		
		return this;
	}
	//private methods
	private float calculateLength(float x, float y)
	{
		return (float) Math.abs(Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
	}
	private void calculateLength()
	{
		length = calculateLength(this.x, this.y);
	}
	
}
